home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 2324 / 2324.xpi / chrome / sessionmanager.jar / content / sessionmanager / session_prompt.js < prev    next >
Encoding:
JavaScript  |  2009-11-07  |  27.1 KB  |  746 lines

  1. var gParams = window.arguments[0].QueryInterface(Components.interfaces.nsIDialogParamBlock);
  2. var gSessionTree = null;
  3. var gTextBox = null;
  4. var ggMenuList = null;
  5. var gTabTree = null;
  6. var gTabTreeBox = null;
  7. var gTreeSplitter = null;
  8. var gCtrlClickNote = null;
  9. var gAcceptButton = null;
  10. var gExtraButton = null;
  11. var gSessionNames = {};
  12. var gGroupNames = [];
  13. var gBackupGroupName = null;
  14. var gBannedNames = [];
  15. var gBackupNames = [];
  16. var gSessionTreeData = [];
  17. var gOriginalSessionTreeData;
  18. // gExistingName is the index of the item with the name in the text field.  -1 means no match
  19. var gExistingName = -1;
  20. var gNeedSelection = false;
  21. var gWidth = 0;
  22. var gInvalidTime = false;
  23. var gAlreadyResized = false;
  24. var gFinishedLoading = false;
  25.  
  26. var gAppendToSessionFlag = false;
  27.  
  28. // Used to keep track of the accept button position change
  29. var gLastAcceptPosition = 0;
  30. var gLastGoodHeight = 0;
  31. var gOldLastGoodHeight = 0;
  32. var gHeightBeforeCollapse = 0;
  33. var gTimerId = null;
  34.  
  35. var sortedBy = 0;
  36.  
  37. // GetInt 1 bit values
  38. // 1   = add current session - used when recovering from crash
  39. // 2   = multiselect enable  - true if allowed to choose multiple sessions (used for deleting)
  40. // 4   = ignorable           - Displays ignore checkbox
  41. // 8   = autosaveable        - Displays autosave checkbox
  42. // 16  = remove              - true if deleting session(s)
  43. // 32  = grouping            - true if changing grouping
  44. // 64  = append/replace      - true if displaying the append/replace radio group, false otherwise
  45. // 128 = preselect           - true if preselecting last backup session
  46. // 256 = allow name replace  - true if double clicking a session name on save will replace existing session, but use default session name.
  47. //                                  (This is currently only settable via a userChrome.js script).
  48.  
  49. // GetString values
  50. // 1 = Session Label         - Label at top of window
  51. // 2 = Accept Label          - Okay Button label for normal accept
  52. // 3 = Session Filename      - filename of session save file
  53. // 4 = Text Label            - Label above text box
  54. // 5 = Accept Existing Label - Okay button label when overwriting existing session
  55. // 6 = Default Session Name  - Comes from page title
  56. // 7 = Count String          - Count String for current crashed session
  57.  
  58. // SetInt 0 bit values
  59. // 1 = Accept button pressed
  60.  
  61. // SetInt 1 bit values
  62. // 4  = ignore               - ignore checkbox checked
  63. // 8  = autosave             - autosave checkbox checked
  64. // 16 = tabprompt            - tabprompt checbox checked
  65. // 32 = append flag          - true if append session, false if not
  66. // 64 = append window flag   - true if append to window, false if not
  67.  
  68. // SetString values
  69. // 3 = Session Filename
  70. // 6 = Session Name
  71. // 7 = Group Name
  72.  
  73. gSessionManager._onLoad = gSessionManager.onLoad;
  74. gSessionManager.onLoad = function() {
  75.     this._onLoad(true);
  76.     
  77.     _("mac_title").hidden = !/mac/i.test(navigator.platform);
  78.     setDescription(_("session_label"), gParams.GetString(1));
  79.     
  80.     gAcceptButton = document.documentElement.getButton("accept");
  81.     gAcceptButton.label = gParams.GetString(2) || gAcceptButton.label;
  82.     gExtraButton = document.documentElement.getButton("extra1");
  83.     
  84.     var sessions = null;
  85.     if (window.opener && window.opener.gSessionManager && window.opener.gSessionManager.getSessionsOverride) {
  86.         if (typeof window.opener.gSessionManager.getSessionsOverride == "function") {
  87.             try {
  88.                 sessions = window.opener.gSessionManager.getSessionsOverride();
  89.             } catch (ex) { 
  90.                 this.log("Override function error. " + ex, "ERROR", true);
  91.             }
  92.         }
  93.         else {
  94.             this.log("Passed override function parameter is not a function.", "ERROR", true);
  95.         }
  96.         if (!sessions || !_isValidSessionList(sessions)) {
  97.             window.close();
  98.             return;
  99.         }
  100.     }
  101.     else {
  102.         sessions = this.getSessions();
  103.     }
  104.     
  105.     if (gParams.GetInt(1) & 1) // add a "virtual" current session
  106.     {
  107.         sessions.unshift({ name: this._string("current_session"), fileName: "*" });
  108.     }
  109.     
  110.     gTabTree = _("tabTree");
  111.     gTabTreeBox = _("tabTreeBox");
  112.     gTreeSplitter = _("tree_splitter");
  113.     gCtrlClickNote = _("ctrl_click_note");
  114.     gSessionTree = _("session_tree");
  115.     gSessionTree.selType = (gParams.GetInt(1) & 2)?"multiple":"single";
  116.     
  117.     // Do not allow overwriting of open window or browser sessions
  118.     gBannedNames = this.getWindowSessions();
  119.     var currentSession = this.getPref("_autosave_values", "").split("\n")[0];
  120.     if (currentSession) gBannedNames[currentSession.trim().toLowerCase()] = true;
  121.     
  122.     // hide/show the "Don't show [...] again" checkbox
  123.     _("checkbox_ignore").hidden = !(gParams.GetInt(1) & 4);
  124.  
  125.     // hide/show the Autosave checkboxes
  126.     _("checkbox_autosave").hidden = !(gParams.GetInt(1) & 8);
  127.     _("save_every").hidden = _("checkbox_autosave").hidden || !_("checkbox_autosave").checked;
  128.     
  129.     // hide/show the append/replace radio buttons
  130.     _("radio_append_replace").hidden = !(gParams.GetInt(1) & 64);
  131.     _("radio_append_replace").selectedIndex = this.getPref("overwrite", false) ? 1 : (this.getPref("append_by_default", false) ? 2 : 0);
  132.     if (window.opener && typeof(window.opener.gSingleWindowMode) != "undefined" && window.opener.gSingleWindowMode) {
  133.         if (!_("radio_append_replace").selectedIndex) _("radio_append_replace").selectedIndex = 2;
  134.         _("radio_append").hidden = true;
  135.     }
  136.  
  137.     gBackupGroupName = this._string("backup_sessions");
  138.     gBackupNames[this._string("backup_session").trim().toLowerCase()] = true;
  139.     gBackupNames[this._string("autosave_session").trim().toLowerCase()] = true;
  140.     
  141.     var deleting = (gParams.GetInt(1) & 16);
  142.     var saving = (gParams.GetInt(1) & 8);
  143.     var grouping = (gParams.GetInt(1) & 32);
  144.     var loading = (gParams.GetInt(1) & 64);
  145.     var preselect = (gParams.GetInt(1) & 128);
  146.     var groupCount = 0;
  147.     var selected;
  148.     sessions.forEach(function(aSession) {
  149.         var trimName = aSession.name.trim().toLowerCase();
  150.         // ban backup session names
  151.         if (aSession.backup) gBackupNames[trimName] = true;
  152.         // Don't display loaded sessions in list for load or save or backup items in list for save or grouping
  153.         if (!((aSession.backup && (saving || grouping)) || ((gBannedNames[trimName]) && (saving || loading))))
  154.         {
  155.             // get window and tab counts and group name for crashed session
  156.             if (aSession.fileName == "*") {
  157.                 aSession.group = gBackupGroupName;
  158.                 var counts = gParams.GetString(7).split(",");
  159.                 aSession.windows = counts[0];
  160.                 aSession.tabs = counts[1];
  161.             }
  162.             
  163.             // Break out Autosave variables
  164.             if (aSession.autosave) {
  165.                 var autosave = aSession.autosave.split("/");
  166.                 aSession.autosave = autosave[0];
  167.                 aSession.autosave_time = autosave[1];
  168.             }
  169.             
  170.             // Mark if session loaded
  171.             aSession.loaded = gBannedNames[trimName] || null;
  172.             
  173.             // Flag latest session
  174.             if ((sessions.latestTime && (sessions.latestTime == aSession.timestamp) && !(gParams.GetInt(1) & 1)) || (aSession.fileName == "*")) {
  175.                 aSession.latest = true;
  176.             }
  177.             
  178.             // Select previous session if requested to do so and no session name passed
  179.             if (preselect && aSession.backup && !gParams.GetString(3) && (sessions.latestBackUpTime == aSession.timestamp)) {
  180.                 selected = gSessionTreeData.length;
  181.             }
  182.  
  183.             // select passed in item (if any)
  184.             if (aSession.fileName == gParams.GetString(3)) selected = gSessionTreeData.length;
  185.  
  186.             // Add session to name list
  187.             gSessionNames[trimName] = gSessionTreeData.length;
  188.             
  189.             // Push to Tree database and backup
  190.             gSessionTreeData.push(aSession);
  191.             
  192.             // Build group menu list
  193.             if (aSession.group && !aSession.backup) {
  194.                 var regExp = new RegExp("^" + aSession.group + "|," + aSession.group + "$|," + aSession.group + ",");
  195.                 if (!regExp.test(gGroupNames.toString())) {
  196.                     gGroupNames[groupCount++] = aSession.group.trim();
  197.                 }
  198.             }
  199.         }
  200.     }, this);
  201.     
  202.     // Make a copy of array
  203.     gOriginalSessionTreeData = gSessionTreeData.slice(0);
  204.     
  205.     // Display Tree
  206.     gSessionTree.view = sessionTreeView;
  207.     
  208.     // select passed in item (if any)
  209.     if (selected != undefined) gSessionTree.view.selection.select(selected);
  210.  
  211.     // If there is a text box label, enable text boxes
  212.     if (gParams.GetString(4))
  213.     {
  214.         _("text_container").hidden = false;
  215.         setDescription(_("text_label"), gParams.GetString(4));
  216.         
  217.         // If renaming and name already entered, disable the session selection list
  218.         if (gParams.GetString(3) && !gParams.GetString(5)) gSessionTree.disabled = true;
  219.  
  220.         // group text input is enabled when saving or group changing
  221.         if ((gParams.GetInt(1) & 32) || gParams.GetString(5)) 
  222.         {
  223.             _("group-text-container").hidden = false;
  224.             ggMenuList = _("group_menu_list");
  225.  
  226.             // Pre-populate Group Menu
  227.             gGroupNames.sort();
  228.             for (var i in gGroupNames) {
  229.                 ggMenuList.appendItem(gGroupNames[i]);
  230.             }
  231.         }
  232.                 
  233.         // session text input is enabled when not group changing (i.e., when saving or renaming)
  234.         if (!(gParams.GetInt(1) & 32)) 
  235.         {
  236.             _("session-text-container").hidden = false;
  237.             gTextBox = _("text_box");
  238.         
  239.             // Pre-populate the text box with default session name if saving and the name is not banned or already existing.
  240.             // Otherwise disable accept button
  241.             var trimname = gParams.GetString(6).trim().toLowerCase();
  242.             if (gParams.GetString(5) && !gBannedNames[trimname] && ((gSessionNames[trimname] == undefined) || (gParams.GetInt(1) & 256)))
  243.             {
  244.                 onTextboxInput(gParams.GetString(6));
  245.             }
  246.             else gAcceptButton.disabled = true;
  247.         }
  248.     }
  249.     
  250.     // Force user to make a selection if no text or group box or not saving (i.e., deleting or renaming)
  251.     if ((gNeedSelection = !gTextBox || !ggMenuList || !gParams.GetString(5)) || (gParams.GetInt(1) & 256))
  252.     {
  253.         gSessionTree.addEventListener("select", onSessionTreeSelect, false);
  254.         onSessionTreeSelect();
  255.     }
  256.     
  257.     if (gSessionTree.hasAttribute("height"))
  258.     {
  259.         gSessionTree.height = gSessionTree.getAttribute("height");
  260.     }
  261.     if (!window.opener)
  262.     {
  263.         document.title += " - " + document.getElementById("bundle_brand").getString("brandFullName");
  264.         document.documentElement.removeAttribute("screenX");
  265.         document.documentElement.removeAttribute("screenY");
  266.  
  267.         // Move window so that the bottom part can be displayed when prompting for a session that
  268.         // does not select the session by default
  269.         if (!gParams.GetString(3)) {
  270.             setTimeout( function() {
  271.                 var tabHeight = gTabTree.getAttribute("height");
  272.                 var adjustHeight = window.screen.availHeight - tabHeight - window.outerHeight - window.screenY - 54;
  273.                 if ((window.screenY + adjustHeight) < 0) adjustHeight = -window.screenY;
  274.                 if (adjustHeight < 0) window.moveBy(0, adjustHeight);
  275.             },0);
  276.         }
  277.     }
  278.     window.sizeToContent();
  279.     
  280.     // watch for resize to prevent user from shrinking window so small it hides dialog buttons.
  281.     window.onresize = resize;
  282.     
  283.     gFinishedLoading = true;
  284. };
  285.  
  286. gSessionManager.onWindowClose = function() {};
  287.  
  288. gSessionManager.onUnload = function() {
  289.     function persist(aObj, aAttr, aValue)
  290.     {
  291.         aObj.setAttribute(aAttr, aValue);
  292.         document.persist(aObj.id, aAttr);
  293.     }
  294.     
  295.     if (window.opener)
  296.     {
  297.         persist(document.documentElement, "screenX", window.screenX - window.opener.screenX);
  298.         persist(document.documentElement, "screenY", window.screenY - window.opener.screenY);
  299.     }
  300.     
  301.     // only persist tree heights is neither is collapsed to prevent "giant" trees
  302.     if (gTreeSplitter.getAttribute("state") != "collapsed") {
  303.         // persist session tree height if it has a height, subtract one if tab Tree is hidden because one is added if it is
  304.         if (gSessionTree && gSessionTree.treeBoxObject.height > 0) {
  305.             var tweak = gTabTreeBox.hidden ? 1 : 0;
  306.             persist(gSessionTree, "height", gSessionTree.treeBoxObject.height - tweak);
  307.         }
  308.         // persist tab tree height if it has a height, subtract 13 from the clicknoteHeight because it overcalculates by 13.
  309.         if (gTabTree && gTabTree.treeBoxObject.height > 0) {
  310.             persist(gTabTree, "height", gTabTree.treeBoxObject.height);
  311.             var clickNoteHeight = parseInt(window.getComputedStyle(gCtrlClickNote, null).height);
  312.             clickNoteHeight = isNaN(clickNoteHeight) ? 0 : clickNoteHeight - 13;
  313.             persist(gTabTree, "height", gTabTree.treeBoxObject.height + clickNoteHeight);
  314.         }
  315.     }
  316.     //dump(gSessionTree.getAttribute("height") + " " + gTabTree.getAttribute("height") + "\n");
  317.     
  318.     if (!gAllTabsChecked) storeSession();
  319.     
  320.     gParams.SetInt(1, ((_("checkbox_ignore").checked)?4:0) | ((_("checkbox_autosave").checked)?8:0) |
  321.                       ((!gAllTabsChecked)?16:0) | ((_("radio_append").selected && !_("radio_append_replace").hidden)?32:0) | (gAppendToSessionFlag?32:0) |
  322.                       ((_("radio_append_window").selected)?64:0));
  323.     if (_("checkbox_autosave").checked) gParams.SetInt(2, parseInt(_("autosave_time").value.trim()));
  324. };
  325.  
  326. function onSessionTreeClick(aEvent)
  327. {
  328.     if ((aEvent.button == 0) && !aEvent.metaKey && !aEvent.ctrlKey && !aEvent.shiftKey && !aEvent.altKey) {
  329.         if (aEvent.target.nodeName=="treechildren") {
  330.             switch (aEvent.type) {
  331.                 case "click":
  332.                     if (gTextBox && !(gParams.GetInt(1) & 256)) onTextboxInput(gSessionTreeData[gSessionTree.currentIndex].name);
  333.                     break;
  334.                 case "dblclick":
  335.                     gAcceptButton.doCommand();
  336.                     break;
  337.             }
  338.         }
  339.         else if ((aEvent.type == "click") && (aEvent.target.nodeName == "treecol")) {
  340.             var types = { name: 0, group: 1, win_count: 2, tab_count: 3 };
  341.             var which = types[aEvent.target.id];
  342.             
  343.             // If not already sorted, sortedBy will be 0.  Otherwise it is which + 1 if sorted or -(which + 1) if inversely sorted
  344.             var flag = (Math.abs(sortedBy) == (which + 1)) ? (-sortedBy / Math.abs(sortedBy)) : 1
  345.             
  346.             // Save selected items so they can be restored
  347.             var selectedFileNames = {};
  348.             var start = new Object();
  349.             var end = new Object();
  350.             var numRanges = gSessionTree.view.selection.getRangeCount();
  351.  
  352.             for (var t = 0; t < numRanges; t++) {
  353.                 gSessionTree.view.selection.getRangeAt(t,start,end);
  354.                 for (var v = start.value; v <= end.value; v++){
  355.                     selectedFileNames[gSessionTreeData[v].fileName] = true;
  356.                 }
  357.             }
  358.             
  359.             // Clear all selected items
  360.             gSessionTree.view.selection.clearSelection();
  361.             
  362.             // If inversely sorted and user clicks header again, go back to original order
  363.             if (flag && sortedBy < 0) {
  364.                 flag = 0;
  365.                 gSessionTreeData = gOriginalSessionTreeData.slice(0);
  366.             }
  367.             else {
  368.                 // Sort depending on which header is clicked
  369.                 switch (which) {
  370.                     case 0:
  371.                         gSessionTreeData = gSessionTreeData.sort(function(a, b) { 
  372.                             return flag * (a.name.toLowerCase().localeCompare(b.name.toLowerCase())); 
  373.                         });
  374.                         break;
  375.                     case 1:
  376.                         gSessionTreeData = gSessionTreeData.sort(function(a, b) { 
  377.                             return flag * (a.group.toLowerCase().localeCompare(b.group.toLowerCase())); 
  378.                         });
  379.                         break;
  380.                     case 2:
  381.                         gSessionTreeData = gSessionTreeData.sort(function(a, b) { 
  382.                             return flag * (parseInt(a.windows) - parseInt(b.windows)); 
  383.                         });
  384.                         break;
  385.                     case 3:
  386.                         gSessionTreeData = gSessionTreeData.sort(function(a, b) { 
  387.                             return flag * (parseInt(a.tabs) - parseInt(b.tabs)); 
  388.                         });
  389.                         break;
  390.                 }
  391.             }
  392.             
  393.             // Recreate Session List index and restore selected items
  394.             for (var i=0; i<gSessionTreeData.length; i++) {
  395.                 var trimName = gSessionTreeData[i].name.trim().toLowerCase();
  396.                 gSessionNames[trimName] = i;
  397.                 
  398.                 if (selectedFileNames[gSessionTreeData[i].fileName]) {
  399.                     gSessionTree.view.selection.toggleSelect(i);
  400.                 }
  401.             }
  402.             sortedBy = flag * (which + 1);
  403.  
  404.             // update header arrorws            
  405.             for (var i=0; i < aEvent.target.parentNode.childNodes.length; i++) {
  406.                 var sortText = flag ? ((flag>0) ? "ascending" : "descending") : "natural";
  407.                 aEvent.target.parentNode.childNodes[i].setAttribute("sortDirection", ((aEvent.target.parentNode.childNodes[i] == aEvent.target) ? sortText : "natural"))
  408.             }
  409.             
  410.             // Redraw the tree - Needed for OS X
  411.             gSessionTree.treeBoxObject.invalidate();
  412.         }
  413.     }
  414. }
  415.  
  416. function onSessionTreeKeyPress(aEvent)
  417. {
  418.     if (gTextBox && (aEvent.keyCode == aEvent.DOM_VK_RETURN) && (gSessionTree.view.selection.count > 0)) {
  419.         onTextboxInput(gSessionTreeData[gSessionTree.currentIndex].name);
  420.         aEvent.preventDefault();
  421.     }
  422. }
  423.  
  424. function onSessionTreeSelect()
  425. {
  426.     // If no session name or group name text box, disable the accept button if nothing selected.
  427.     // Otherwise isAcceptable when changing groups or onTextboxInput otherwise.
  428.     if (!gTextBox && !ggMenuList)
  429.     {
  430.         gAcceptButton.disabled = gSessionTree.view.selection.count == 0;
  431.         
  432.         // save current session tree height before doing any unhiding (subtract one since one gets added for some reason)
  433.         var currentSessionTreeHeight = gSessionTree.treeBoxObject.height - 1;
  434.         
  435.         // hide tab tree and splitter if nothing selected or multiple selection is enabled (deleting) and more than one or no session is selected
  436.         // hide the click note if append/replace buttons are displayed (manual load)
  437.         var hideTabTree = gAcceptButton.disabled || ((gParams.GetInt(1) & 2) && gSessionTree.view.selection.count != 1);
  438.         gTreeSplitter.hidden = gTabTreeBox.hidden = hideTabTree;
  439.         gCtrlClickNote.hidden = hideTabTree || !(gParams.GetInt(1) & 64);
  440.         
  441.         // if displaying the tab tree, initialize it and then, if the tab tree was hidden, 
  442.         // resize the window based on the current persisted height of the tab tree and the
  443.         // current session tree height.  
  444.         if (!hideTabTree) {
  445.             // if deleting, change column label
  446.             if (gParams.GetInt(1) & 2) {
  447.                 _("restore").setAttribute("label", gSessionManager._string("remove_session_ok"));
  448.             }
  449.             initTreeView(gSessionTreeData[gSessionTree.currentIndex].fileName, (gParams.GetInt(1) & 2));
  450.             if (!gAlreadyResized && gFinishedLoading) {
  451.                 gAlreadyResized = true;
  452.                 if (gTabTree.hasAttribute("height"))
  453.                 {
  454.                     gTabTree.height = gTabTree.getAttribute("height");
  455.                 }
  456.                 gSessionTree.height = currentSessionTreeHeight;
  457.                 
  458.                 // The following line keeps the window width from increasing when sizeToContent is called.
  459.                 _("sessionmanagerPrompt").width = window.innerWidth - 1;
  460.                 window.sizeToContent();
  461.             }
  462.         }
  463.     }
  464.     else
  465.     {
  466.         if (gTextBox) onTextboxInput();
  467.         else isAcceptable();
  468.     }
  469. }
  470.  
  471. function onTextboxInput(aNewValue)
  472. {
  473.     if (aNewValue)
  474.     {
  475.         var match = /   \([0-9]+\/[0-9]+\)$/m.exec(aNewValue);
  476.         if (match)
  477.         {
  478.             aNewValue = aNewValue.substring(0,match.index);
  479.         }
  480.         gTextBox.value = aNewValue;
  481.         setTimeout(function() { gTextBox.select(); gTextBox.focus(); }, 0);
  482.     }
  483.     
  484.     var input = gTextBox.value.trim().toLowerCase();
  485.     var oldWeight = !!gAcceptButton.style.fontWeight;
  486.     
  487.     gExistingName = (gSessionNames[input] != undefined) ? gSessionNames[input] : -1;
  488.     var newWeight = !!((gExistingName >= 0) || ((gParams.GetInt(1) & 256) && gSessionTree.view.selection.count > 0));
  489.     
  490.     if (!_("checkbox_autosave").hidden) {
  491.         var currentChecked = _("checkbox_autosave").checked;
  492.         if (gExistingName >= 0) {
  493.             _("checkbox_autosave").checked = gSessionTreeData[gExistingName].autosave != "false";
  494.             _("autosave_time").value = gSessionTreeData[gExistingName].autosave_time || "";
  495.         }
  496.         else {
  497.             _("checkbox_autosave").checked = false;
  498.             _("autosave_time").value = "";
  499.         }
  500.         if (currentChecked != _("checkbox_autosave").checked) _save_every_update();
  501.     }
  502.     
  503.     if (!gNeedSelection && oldWeight != newWeight)
  504.     {
  505.         gAcceptButton.label = (newWeight && gParams.GetString(5))?gParams.GetString(5):gParams.GetString(2);
  506.         gAcceptButton.style.fontWeight = (newWeight)?"bold":"";
  507.         // Show append button if replace button is shown.
  508.         gExtraButton.hidden = gAcceptButton.label != gParams.GetString(5)
  509.     }
  510.     gExtraButton.disabled = gExtraButton.hidden || _("checkbox_autosave").checked;
  511.  
  512.     // Highlight matching item when accept label changes to replace and copy in group value (only when saving and not replacing name)
  513.     if (newWeight && gParams.GetString(5) && !(gParams.GetInt(1) & 256)) {
  514.         gSessionTree.view.selection.select(gExistingName);
  515.         if (ggMenuList) ggMenuList.value = gSessionTreeData[gExistingName].group;
  516.     }
  517.         
  518.     isAcceptable();
  519. }
  520.  
  521. function isAcceptable() 
  522. {
  523.     var badSessionName = false;
  524.     var badGroupName = false;
  525.     
  526.     if (ggMenuList) {
  527.         var groupName = ggMenuList.value.trim();
  528.         badGroupName = (groupName == gBackupGroupName)
  529.         ggMenuList.inputField.setAttribute("badname", badGroupName);
  530.     }
  531.     
  532.     if (gTextBox) {
  533.         var input = gTextBox.value.trim().toLowerCase();
  534.         gTextBox.setAttribute("badname", gBackupNames[input]);
  535.         badSessionName = !input || gBackupNames[input] || gBannedNames[input];
  536.     }
  537.     
  538.     gAcceptButton.disabled = gInvalidTime || badSessionName || badGroupName || (gNeedSelection && (gSessionTree.view.selection.count == 0 || (gExistingName >= 0)));
  539. }
  540.  
  541. function onAcceptDialog(aParam)
  542. {
  543.     // Only set to true if user clicked extra1 button
  544.     gAppendToSessionFlag = aParam;
  545.  
  546.     gParams.SetInt(0, 1);
  547.     if (gNeedSelection || ((gParams.GetInt(1) & 256) && gSessionTree.view.selection.count > 0))
  548.     {
  549.         var selectedFileNames = [];
  550.         var start = new Object();
  551.         var end = new Object();
  552.         var numRanges = gSessionTree.view.selection.getRangeCount();
  553.  
  554.         for (var t = 0; t < numRanges; t++) {
  555.             gSessionTree.view.selection.getRangeAt(t,start,end);
  556.             for (var v = start.value; v <= end.value; v++){
  557.                 selectedFileNames.push(gSessionTreeData[v].fileName);
  558.             }
  559.         }
  560.         gParams.SetString(3, selectedFileNames.join("\n"));
  561.     }
  562.     else if (gExistingName >= 0)
  563.     {
  564.         var dontPrompt = { value: false };
  565.         if (gAppendToSessionFlag || gSessionManager.getPref("no_overwrite_prompt") || gSessionManager.mPromptService.confirmEx(null, gSessionManager.mTitle, gSessionManager._string("overwrite_prompt"), gSessionManager.mPromptService.BUTTON_TITLE_YES * gSessionManager.mPromptService.BUTTON_POS_0 + gSessionManager.mPromptService.BUTTON_TITLE_NO * gSessionManager.mPromptService.BUTTON_POS_1, null, null, null, gSessionManager._string("prompt_not_again"), dontPrompt) == 0)
  566.         {
  567.             gParams.SetString(3, gSessionTreeData[gExistingName].fileName);
  568.             if (dontPrompt.value)
  569.             {
  570.                 gSessionManager.setPref("no_overwrite_prompt", true);
  571.             }
  572.         }
  573.         else {
  574.             gParams.SetInt(0, 0);
  575.             return false;
  576.         }
  577.     }
  578.     else
  579.     {
  580.         gParams.SetString(3, "");
  581.     }
  582.     gParams.SetString(6, _("text_box").value.trim());
  583.     gParams.SetString(7, _("group_menu_list").value.trim());
  584.     
  585.     // Click extra button doesn't close window so do that here
  586.     if (gAppendToSessionFlag) window.close();
  587. }
  588.  
  589. function setDescription(aObj, aValue)
  590. {
  591.     aValue.split("\n").forEach(function(aLine) {
  592.         aObj.appendChild(document.createElement("description")).textContent = aLine;
  593.     });
  594. }
  595.  
  596. function _(aId)
  597. {
  598.     return document.getElementById(aId);
  599. }
  600.  
  601. function _isValidSessionList(aSessions)
  602. {
  603.     if (aSessions==null || typeof(aSessions)!="object" || typeof(aSessions.length)!="number" || 
  604.         aSessions.length == 0 || !aSessions[0].name) {
  605.         this.log("Override function returned an invalid session list.", "ERROR", true);
  606.         return false;
  607.     }
  608.     return true;
  609. }
  610.  
  611. function _save_every_update()
  612. {
  613.     var checked = _('checkbox_autosave').checked;
  614.     
  615.     _('save_every').hidden = !checked;
  616.     
  617.     // resize window
  618.     if (checked) {
  619.         this._save_every_height = parseInt(window.getComputedStyle(_('save_every'), "").height);
  620.         if (isNaN(this._save_every_height)) this._save_every_height = 0;
  621.         window.innerHeight += this._save_every_height;
  622.     }
  623.     else {
  624.         if (this._save_every_height) window.innerHeight -= this._save_every_height;
  625.     }
  626. }
  627.  
  628. function isNumber(aTextBox)
  629. {
  630.     gInvalidTime = !/^([1-9]\d*)?$/.test(aTextBox.value);
  631.     aTextBox.setAttribute("badname", gInvalidTime ? "true" : "false");
  632.     
  633.     isAcceptable();
  634. }
  635.  
  636. // if the accept button is no longer moving when resizing, the window is too small so make it bigger.
  637. function resize(aEvent, aString)
  638. {
  639.     // when collapsing a tree save old good height (if not already saved) and then restore it when opening a tree
  640.     if (aString == "collapsed") {
  641.         if (!gHeightBeforeCollapse) gHeightBeforeCollapse = gOldLastGoodHeight;
  642.         return;
  643.     }
  644.     else if (aString == "open") {
  645.         gOldLastGoodHeight = gHeightBeforeCollapse;
  646.         gHeightBeforeCollapse = 0;
  647.     }
  648.  
  649.     var currentAcceptPosition = gAcceptButton.boxObject.y + gAcceptButton.boxObject.height;
  650.     // only restore window height if accept button didn't move and window was shrunk or tree splitter was opened
  651.     if (((currentAcceptPosition == gLastAcceptPosition) || (aString == "open")) && (window.outerHeight < gOldLastGoodHeight)) {
  652.         if (gTimerId) {
  653.             clearTimeout(gTimerId);
  654.             delete gTimerId;
  655.         }
  656.         gTimerId = setTimeout(function() {window.resizeTo(window.outerWidth,gOldLastGoodHeight);}, 100);
  657.     }
  658.     else {
  659.         // Save last good height and use that in case current accept position is the smallest
  660.         gOldLastGoodHeight = gLastGoodHeight;
  661.         gLastGoodHeight = window.outerHeight;
  662.     }
  663.     gLastAcceptPosition = currentAcceptPosition;
  664. }
  665.  
  666. // Tree controller
  667.  
  668. var sessionTreeView = {
  669.     _atoms: {},
  670.     _getAtom: function(aName)
  671.     {
  672.         if (!this._atoms[aName]) {
  673.             var as = Components.classes["@mozilla.org/atom-service;1"].getService(Components.interfaces.nsIAtomService);
  674.             this._atoms[aName] = as.getAtom(aName);
  675.         }
  676.         return this._atoms[aName];
  677.     },
  678.  
  679.     treeBox: null,
  680.     selection: null,
  681.  
  682.     get rowCount()                     { return gSessionTreeData.length; },
  683.     setTree: function(treeBox)         { this.treeBox = treeBox; },
  684.     getCellText: function(idx, column) { 
  685.         switch(column.id) {
  686.             case "name":
  687.                 return gSessionTreeData[idx].name;
  688.                 break;
  689.             case "group":
  690.                 return gSessionTreeData[idx].group;
  691.                 break;
  692.             case "win_count":
  693.                 return gSessionTreeData[idx].windows;
  694.                 break;
  695.             case "tab_count":
  696.                 return gSessionTreeData[idx].tabs;
  697.                 break;
  698.         }
  699.         return null;
  700.     },
  701.     canDrop: function(idx, orient)      { return false; },
  702.     isContainer: function(idx)          { return false; },
  703.     isContainerOpen: function(idx)      { return false; },
  704.     isContainerEmpty: function(idx)     { return false; },
  705.     isSelectable: function(idx, column) { return false; },
  706.     isSeparator: function(idx)          { return false; },
  707.     isSorted: function()                { return sortedBy != 0; },
  708.     isEditable: function(idx, column)   { return false; },
  709.     getLevel: function(idx)             { return 0; },
  710.     getParentIndex: function(idx)       { return -1; },
  711.     getImageSrc: function(idx, column)  { return null; },
  712.  
  713.     hasNextSibling: function(idx, after) {
  714.         return (idx <= after) && (idx < gSessionTreeData.length - 1) && (after < gSessionTreeData.length - 1);
  715.     },
  716.  
  717.     getCellProperties: function(idx, column, prop) {
  718.         if ((column.id == "group") && (gSessionTreeData[idx].backup)) 
  719.             prop.AppendElement(this._getAtom("disabled"));
  720.         if (gSessionTreeData[idx].latest) 
  721.             prop.AppendElement(this._getAtom("latest"));
  722.         if (gSessionTreeData[idx].loaded)
  723.             prop.AppendElement(this._getAtom("disabled"));
  724.         if (gSessionTreeData[idx].autosave)
  725.             prop.AppendElement(this._getAtom(gSessionTreeData[idx].autosave));
  726.     },
  727.  
  728.     getRowProperties: function(idx, prop) {
  729.         if (idx % 2 != 0)
  730.             prop.AppendElement(this._getAtom("alternate"));
  731.     },
  732.  
  733.     drop: function(row, orient) { },
  734.     getCellValue: function(idx, column) { },
  735.     getProgressMode : function(idx, column) { },
  736.     toggleOpenState: function(idx) { },
  737.     cycleHeader: function(column) { },
  738.     cycleCell: function(idx, column) { },
  739.     selectionChanged: function() { },
  740.     setCellValue: function() { },
  741.     setCellText: function() { },
  742.     performAction: function(action) { },
  743.     performActionOnCell: function(action, index, column) { },
  744.     performActionOnRow: function(action, index) { },
  745.     getColumnProperties: function(column, prop) { }
  746. };